///////////////////////////////////////////////////////////
//  GameApplication.h
//  Implementation of the Class GameApplication
//  Created on:      11-Jan-2015 4:13:26 PM
//  Original author: Eng. Ahmed Yasser
///////////////////////////////////////////////////////////

#if !defined(EA_428BF422_3C4A_4092_AE66_E70A55A6EB99__INCLUDED_)
#define EA_428BF422_3C4A_4092_AE66_E70A55A6EB99__INCLUDED_

#include <vector>
#include <string>

#include "IGameApplicationObserver.h"
#include "IGameWindowObserver.h"
#include "..\EngineUtilities\IGameTimer.h"
#include "..\EngineProfile\IGameLog.h"
#include "IGameApplication.h"
#include "IGameWindow.h"

namespace EngineGame
{
	namespace EngineCore
	{
		/**
		 * The Basic game application that implement the interface IGameApplication and
		 * provide the basic implementation to any game
		 * @author Eng. Ahmed Yasser
		 * @version 1.0
		 * @updated 12-Jan-2015 1:09:48 PM
		 */
		class GameApplication : public EngineGame::EngineCore::IGameApplicationObserver, public EngineGame::EngineCore::IGameWindowObserver, public EngineGame::EngineCore::IGameApplication
		{

		public:
			EngineGame::EngineProfile::IGameLogManager *_IGameLogManager;
			GameApplication();
			virtual ~GameApplication();
			GameApplication(const GameApplication& theGameApplication);

			/**
			 * Add a new game application observer to observe the game application events
			 * 
			 * @param gameApplicationObserver    The game application observer to be added
			 */
			virtual void addGameApplicationObserver(IGameApplicationObserver* gameApplicationObserver);
			/**
			 * Clear the list of the game application observers
			 */
			virtual void clearGameAppplicationObservers();
			/**
			 * returns the instance of the application that created the game
			 */
			HINSTANCE getAppInstance();
			/**
			 * Returns the game logger that is attached with the game application
			 */
			EngineGame::EngineProfile::IGameLog* getGameLogger();
			/**
			 * Returns the game timer attached with the game application
			 */
			EngineGame::EngineUtilities::IGameTimer* getGameTimer();
			/**
			 * returns the title of the game
			 */
			std::string getGameTitle();
			/**
			 * returns the game window attached with the application
			 */
			IGameWindow* getGameWindow();
			/**
			 * Initialize the game resources and load required data for running the game
			 * 
			 * @param hInstance    The handle of the application
			 * @param gameTitle    The title of the game
			 * @param windowWidth    The width of the window that will hold the game
			 * @param windowHeight    The height of the window that will hold the game
			 */
			virtual bool initGame(HINSTANCE hInstance, std::string gameTitle = "Game Application", int windowWidth = 800, int windowHeight = 600);
			/**
			 * Remove the game application observer from the observers list
			 * 
			 * @param gameApplicationObserver
			 */
			virtual void removeGameApplicationObserver(IGameApplicationObserver* gameApplicationObserver);
			/**
			 * Start running the game loop
			 */
			virtual void runGame();
			/**
			 * Shutdown the game and finalize any resources in the game
			 */
			virtual void shutdownGame();

		protected:
			/**
			 * The title of the game
			 */
			std::string _gameTitle;
			/**
			 * The instance of the application
			 */
			HINSTANCE _hInstance;
			/**
			 * The game timer that will be used in managing the time in the game application,
			 * it will use the GameTimeMultimedia as default timer
			 */
			EngineGame::EngineUtilities::IGameTimer *_gameTimer;
			/**
			 * The logger that will be used in  logging any info in the game
			 */
			EngineGame::EngineProfile::IGameLog *_gameLogger;
			/**
			 * The list of all game application observers that is attached to the game
			 * application
			 */
			std::vector<IGameApplicationObserver*>_gameApplicationObservers;
			/**
			 * The game window that is created with the application
			 */
			EngineGame::EngineCore::IGameWindow *_gameWindow;
			/**
			 * The game log manager used in logging application messages
			 */
			EngineGame::EngineProfile::IGameLogManager *_gameLogManager;

			/**
			 * Creates the game logger, if the client need any customizatin for the logger,
			 * reimplemet this function
			 */
			virtual void createGameLog();
			/**
			 * Creates the game time, if the client need any customizatin for the timer,
			 * reimplemet this function
			 */
			virtual void createGameTimer();
			/**
			 * Created the game window of the application, if the client needs any
			 * customization for the window created, reimplement this function
			 */
			virtual void createGameWindow();
			/**
			 * In this function, the caller will write any code related to the input handling
			 * from user
			 */
			virtual void handleInput();
			/**
			 * Handle event when a frame begins rendered on the game application
			 * 
			 * @param gameApplication
			 */
			virtual void onApplicationBeginFrame(IGameApplication* gameApplication);
			/**
			 * Handle event of the game application ending
			 * 
			 * @param gameApplication
			 */
			virtual void onApplicationEnd(IGameApplication* gameApplication);
			/**
			 * Handle event when a frame ends rendered on the game application
			 * 
			 * @param gameApplication
			 */
			virtual void onApplicationEndFrame(IGameApplication* gameApplication);
			/**
			 * Handle event of the starting game application
			 * 
			 * @param gameApplication    The game application that called the event
			 */
			virtual void onApplicationStart(IGameApplication* gameApplication);
			/**
			 * The caller implement this function to init his own game resources
			 */
			virtual void onInit();
			/**
			 * Contains any rendering code in the application, any inherited class needs to
			 * render drawing must reimplement this function
			 */
			virtual void onRender();
			/**
			 * In this function, any updates to the data or entities in the game will be
			 * handled here
			 * 
			 * @param elapsedTime    The elapsed time from the last time this function called
			 */
			virtual void onUpdate(double elapsedTime);
			/**
			 * Event occured when the window closed
			 * 
			 * @param gameWindow
			 */
			virtual void onWindowClosed(IGameWindow* gameWindow);
			/**
			 * Events occured when  the window created
			 * 
			 * @param gameWindow    The game window that called this event
			 */
			virtual void onWindowCreated(IGameWindow* gameWindow);
			/**
			 * Event occured when the window destroyed
			 * 
			 * @param gameWindow
			 */
			virtual void onWindowDestroyed(IGameWindow* gameWindow);
			/**
			 * Event occured when the window resized
			 * 
			 * @param gameWindow
			 * @param width    The new width of the window
			 * @param height    The new height of the window
			 */
			virtual void onWindowResized(IGameWindow* gameWindow, int width, int height);

		};

	}

}
#endif // !defined(EA_428BF422_3C4A_4092_AE66_E70A55A6EB99__INCLUDED_)
